/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_ttc7_odscrarr.c                                */
/*  NOTE      =                                                    */
/*  DATE      = 2015/01/30 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>

#include "frcomm.h"
#include "frstr.h"
#include "frmem.h"
#include "frhash2.h"
#include "frlog.h"

#include "conntrack.h"
#include "frct_comm.h"

#include "../../ora_core.h"
#include "../../comm/ora_comm.h"
#include "../../comm/ora_stmt.h"
#include "../../comm/ora_util.h"
#include "../ora_mar_engine.h"
#include "ora_ttc7_odscrarr.h"
#include "ora_ttc7_tti_oer.h"
#include "ora_ttc7_tti_uds.h"

/*******************************************************************************
*  FUNC     :  解析odscrarr请求
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc7_odscrarr_unmarshal_req(Conntrack *p_st_conn
                                    , L7session_ora *p_st_sess
                                    , L7_ora_packet *p_st_ora_packet)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_ora_curr_session *p_st_curr_sess = p_st_session_private->p_st_curr_sess;
    Sql_statement *p_st_stmt = NULL;
    char c_tmp = 0;
    short s_tmp = 0;
    long long ll_tmp = 0LL;
    int i_cursor = 0;
    char c_sql_flag = 0;
    int i_sql_len = 0;

    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC) // seqNumber
        goto error;

    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC) // operationflags
        goto error;

    if (ora_mar_unmarshalSWORD(p_st_sess, p_st_ora_packet, &i_cursor) != FR_SUCC) // cursor_id
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_sql_flag) != FR_SUCC) // sqltext.flag
        goto error;
    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_sql_len) != FR_SUCC) // sqlStmt.length
        goto error;
    if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC) // sqlparseversion
        goto error;
    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // udsarrayO2U
        goto error;
    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC) // numudsO2U
        goto error;

    if (i_sql_len > 0)
    {
        if (ora_mar_skipCHR(i_sql_len, p_st_sess, p_st_ora_packet) != FR_SUCC) // sqltext
            goto error;
    }

    if ((p_st_stmt = frdb_get_statement(p_st_session_private->p_hash_stmt, i_cursor)) != NULL)
    {
        p_st_curr_sess->ul_cursor = (unsigned long) i_cursor;

        // 设置l4层信息
        if (frdb_set_resultset_req(p_st_stmt, FRDB_LAST, 0, bytebuff_length(p_st_ora_packet->p_st_packet), &(p_st_ora_packet->st_timestamp_first), &(p_st_ora_packet->st_timestamp_last)) != FR_SUCC)
            goto error;
    }
    else
    {
        ORA_PRINT_EMERG("can not find current cursor:[%d]\n", i_cursor);
        ORA_FRLOG_ERROR("can not find current cursor:[%d]", i_cursor);
    }

    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析odscrarr响应
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc7_odscrarr_unmarshal_resp(Conntrack *p_st_conn
                                    , L7session_ora *p_st_sess
                                    , L7_ora_packet *p_st_ora_packet)
{
    Sql_statement *p_st_stmt = NULL;
    short s_j = 0;
    int i_i = 0;
    int i_numuds = 0;
    int i_loop = 0;

    if ((p_st_stmt = ora_get_current_stmt(p_st_conn)) == NULL)
        goto error;

    while (i_i == 0)
    {
        if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_j) != FR_SUCC) // j
            goto error;

        switch (s_j)
        {
            case 8:
                if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_numuds) != FR_SUCC) // numuds
                    goto error;

                for (i_loop = 0; i_loop < i_numuds; i_loop++)
                {
                    if (ora_ttc7_tti_uds_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet, p_st_stmt) != FR_SUCC)
                        goto error;
                }

                break;

            case 4:
                if (ora_ttc7_tti_oer_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet, APM_ORA_SESS_IS_ODSCRARR, NULL) == FR_FAIL)
                    goto error;

                ORA_PRINT_TIMEVAL("set resp time st_timestamp_first", p_st_ora_packet->st_timestamp_first);
                ORA_PRINT_TIMEVAL("set resp time st_timestamp_last", p_st_ora_packet->st_timestamp_last);
                // 设置l4层信息
                if (frdb_set_resultset_resp(p_st_stmt, FRDB_LAST, 0, bytebuff_length(p_st_ora_packet->p_st_packet), 0, NULL, &(p_st_ora_packet->st_timestamp_first), &(p_st_ora_packet->st_timestamp_last)) != FR_SUCC)
                    goto error;
                i_i = 1;
                break;

            case 9:
                ORA_PRINT_TIMEVAL("set resp time st_timestamp_first", p_st_ora_packet->st_timestamp_first);
                ORA_PRINT_TIMEVAL("set resp time st_timestamp_last", p_st_ora_packet->st_timestamp_last);
                // 设置l4层信息
                if (frdb_set_resultset_resp(p_st_stmt, FRDB_LAST, 0, bytebuff_length(p_st_ora_packet->p_st_packet), 0, NULL, &(p_st_ora_packet->st_timestamp_first), &(p_st_ora_packet->st_timestamp_last)) != FR_SUCC)
                    goto error;
                i_i = 1;
                break;

            default:
                goto error;
        }
    }

    return FR_SUCC;
error:
    return FR_FAIL;
}
